package config

import (
	"fmt"

	"github.com/spf13/viper"
)

// Config application configuration structure
type Config struct {
	App    AppConfig    `mapstructure:"app"`
	MySQL  MySQLConfig  `mapstructure:"mysql"`
	Redis  RedisConfig  `mapstructure:"redis"`
	SMS    SMSConfig    `mapstructure:"sms"`
	JWT    JWTConfig    `mapstructure:"jwt"`
	Log    LogConfig    `mapstructure:"log"`
}

// AppConfig application basic configuration
type AppConfig struct {
	Name    string `mapstructure:"name"`    // application name
	Version string `mapstructure:"version"` // application version
	Mode    string `mapstructure:"mode"`    // run mode: debug, release
	Port    int    `mapstructure:"port"`    // service port
}

// MySQLConfig MySQL database configuration
type MySQLConfig struct {
	Host     string `mapstructure:"host"`     // database host
	Port     int    `mapstructure:"port"`     // database port
	Username string `mapstructure:"username"` // database username
	Password string `mapstructure:"password"` // database password
	Database string `mapstructure:"database"` // database name
	Charset  string `mapstructure:"charset"`  // character set
	MaxIdle  int    `mapstructure:"max_idle"` // max idle connections
	MaxOpen  int    `mapstructure:"max_open"` // max open connections
}

// RedisConfig Redis configuration
type RedisConfig struct {
	Host     string `mapstructure:"host"`     // Redis host
	Port     int    `mapstructure:"port"`     // Redis port
	Password string `mapstructure:"password"` // Redis password
	Database int    `mapstructure:"database"` // Redis database number
	PoolSize int    `mapstructure:"pool_size"` // connection pool size
}

// SMSConfig SMS service configuration
type SMSConfig struct {
	Provider string `mapstructure:"provider"` // SMS service provider: aliyun, tencent
	Aliyun   AliyunSMSConfig `mapstructure:"aliyun"`
	Tencent  TencentSMSConfig `mapstructure:"tencent"`
}

// AliyunSMSConfig Aliyun SMS configuration
type AliyunSMSConfig struct {
	AccessKeyID     string `mapstructure:"access_key_id"`     // Aliyun access key ID
	AccessKeySecret string `mapstructure:"access_key_secret"` // Aliyun access key secret
	SignName        string `mapstructure:"sign_name"`         // SMS signature
	TemplateCode    string `mapstructure:"template_code"`     // SMS template code
	RegionID        string `mapstructure:"region_id"`         // Aliyun region ID
}

// TencentSMSConfig Tencent SMS configuration
type TencentSMSConfig struct {
	SecretID  string `mapstructure:"secret_id"`  // Tencent secret ID
	SecretKey string `mapstructure:"secret_key"` // Tencent secret key
	AppID     string `mapstructure:"app_id"`     // Tencent SMS app ID
	SignName  string `mapstructure:"sign_name"`  // SMS signature
	TemplateID string `mapstructure:"template_id"` // SMS template ID
	Region    string `mapstructure:"region"`     // Tencent region
}

// JWTConfig JWT configuration
type JWTConfig struct {
	Secret     string `mapstructure:"secret"`      // JWT secret key
	ExpireTime int    `mapstructure:"expire_time"` // JWT expire time (hours)
}

// LogConfig log configuration
type LogConfig struct {
	Level      string `mapstructure:"level"`       // log level: debug, info, warn, error
	Format     string `mapstructure:"format"`      // log format: json, text
	Output     string `mapstructure:"output"`      // log output: stdout, file
	FilePath   string `mapstructure:"file_path"`   // log file path
	MaxSize    int    `mapstructure:"max_size"`    // max file size (MB)
	MaxBackups int    `mapstructure:"max_backups"` // max backup files
	MaxAge     int    `mapstructure:"max_age"`     // max age (days)
	Compress   bool   `mapstructure:"compress"`    // compress log files
}

var config *Config

// Init initialize configuration
func Init() error {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("./config")
	viper.AddConfigPath(".")

	// set default values
	setDefaults()

	// read config file
	if err := viper.ReadInConfig(); err != nil {
		return fmt.Errorf("failed to read config file: %w", err)
	}

	// bind environment variables
	viper.SetEnvPrefix("PBJ")
	viper.AutomaticEnv()

	// unmarshal config
	config = &Config{}
	if err := viper.Unmarshal(config); err != nil {
		return fmt.Errorf("failed to unmarshal config: %w", err)
	}

	return nil
}

// GetConfig get configuration instance
func GetConfig() *Config {
	return config
}

// setDefaults set default configuration values
func setDefaults() {
	// app defaults
	viper.SetDefault("app.name", "PBJ Server")
	viper.SetDefault("app.version", "1.0.0")
	viper.SetDefault("app.mode", "debug")
	viper.SetDefault("app.port", 8080)

	// MySQL defaults
	viper.SetDefault("mysql.host", "localhost")
	viper.SetDefault("mysql.port", 3306)
	viper.SetDefault("mysql.username", "root")
	viper.SetDefault("mysql.password", "")
	viper.SetDefault("mysql.database", "pbj_server")
	viper.SetDefault("mysql.charset", "utf8mb4")
	viper.SetDefault("mysql.max_idle", 10)
	viper.SetDefault("mysql.max_open", 100)

	// Redis defaults
	viper.SetDefault("redis.host", "localhost")
	viper.SetDefault("redis.port", 6379)
	viper.SetDefault("redis.password", "")
	viper.SetDefault("redis.database", 0)
	viper.SetDefault("redis.pool_size", 10)

	// SMS defaults
	viper.SetDefault("sms.provider", "aliyun")
	viper.SetDefault("sms.aliyun.region_id", "cn-hangzhou")
	viper.SetDefault("sms.tencent.region", "ap-guangzhou")

	// JWT defaults
	viper.SetDefault("jwt.secret", "pbj-server-secret-key-change-in-production")
	viper.SetDefault("jwt.expire_time", 24)

	// log defaults
	viper.SetDefault("log.level", "info")
	viper.SetDefault("log.format", "json")
	viper.SetDefault("log.output", "stdout")
	viper.SetDefault("log.file_path", "logs/app.log")
	viper.SetDefault("log.max_size", 100)
	viper.SetDefault("log.max_backups", 10)
	viper.SetDefault("log.max_age", 30)
	viper.SetDefault("log.compress", true)
} 